<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <meta name="description" content="User-defined clipping planes applied to a batched 3D Tileset, point cloud, and model.">
    <meta name="cesium-sandcastle-labels" content="Showcases, 3D Tiles">
    <title>Cesium Demo</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script type="text/javascript" src="../../../Build/CesiumUnminified/Cesium.js" nomodule></script>
    <script type="module" src="../load-cesium-es6.js"></script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
    @import url(../templates/bucket.css);
    #toolbar {
        background: rgba(42, 42, 42, 0.8);
        padding: 4px;
        border-radius: 4px;
    }
    #toolbar input {
        vertical-align: middle;
        padding-top: 2px;
        padding-bottom: 2px;
    }
    #toolbar .header {
        font-weight: bold;
    }
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
    <select data-bind="options: exampleTypes, value: currentExampleType"></select>
    <input type="checkbox" value="false" data-bind="checked: debugBoundingVolumesEnabled, valueUpdate: 'input'"> Show bounding volume
    <input type="checkbox" value="true" data-bind="checked: edgeStylingEnabled, valueUpdate: 'input'"> Enable edge styling
</div>

<script id="cesium_sandcastle_script">
function startup(Cesium) {
    'use strict';
//Sandcastle_Begin
// Add a clipping plane, a plane geometry to show the representation of the
// plane, and control the magnitude of the plane distance with the mouse.

var viewer = new Cesium.Viewer('cesiumContainer', {
    infoBox: false,
    selectionIndicator: false,
    terrainProvider: Cesium.createWorldTerrain()
});
var scene = viewer.scene;

var clipObjects = ['BIM', 'Point Cloud', 'Instanced', 'Model'];
var viewModel = {
    debugBoundingVolumesEnabled : false,
    edgeStylingEnabled : true,
    exampleTypes : clipObjects,
    currentExampleType : clipObjects[0]
};

var targetY = 0.0;
var planeEntities = [];
var selectedPlane;
var clippingPlanes;

// Select plane when mouse down
var downHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
downHandler.setInputAction(function(movement) {
    var pickedObject = scene.pick(movement.position);
    if (Cesium.defined(pickedObject) &&
            Cesium.defined(pickedObject.id) &&
            Cesium.defined(pickedObject.id.plane)) {
        selectedPlane = pickedObject.id.plane;
        selectedPlane.material = Cesium.Color.WHITE.withAlpha(0.05);
        selectedPlane.outlineColor = Cesium.Color.WHITE;
        scene.screenSpaceCameraController.enableInputs = false;
    }
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

// Release plane on mouse up
var upHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
upHandler.setInputAction(function() {
    if (Cesium.defined(selectedPlane)) {
        selectedPlane.material = Cesium.Color.WHITE.withAlpha(0.1);
        selectedPlane.outlineColor = Cesium.Color.WHITE;
        selectedPlane = undefined;
    }

    scene.screenSpaceCameraController.enableInputs = true;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

// Update plane on mouse move
var moveHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
moveHandler.setInputAction(function(movement) {
    if (Cesium.defined(selectedPlane)) {
        var deltaY = movement.startPosition.y - movement.endPosition.y;
        targetY += deltaY;
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

function createPlaneUpdateFunction(plane) {
    return function () {
        plane.distance = targetY;
        return plane;
    };
}

var tileset;
function loadTileset(url) {
    clippingPlanes = new Cesium.ClippingPlaneCollection({
        planes : [
            new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 0.0, -1.0), 0.0)
        ],
        edgeWidth : viewModel.edgeStylingEnabled ? 1.0 : 0.0
    });

    tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
        url : url,
        clippingPlanes : clippingPlanes
    }));

    tileset.debugShowBoundingVolume = viewModel.debugBoundingVolumesEnabled;
    return tileset.readyPromise.then(function() {
        var boundingSphere = tileset.boundingSphere;
        var radius = boundingSphere.radius;

        viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0));

        if (!Cesium.Matrix4.equals(tileset.root.transform, Cesium.Matrix4.IDENTITY)) {
            // The clipping plane is initially positioned at the tileset's root transform.
            // Apply an additional matrix to center the clipping plane on the bounding sphere center.
            var transformCenter = Cesium.Matrix4.getTranslation(tileset.root.transform, new Cesium.Cartesian3());
            var transformCartographic = Cesium.Cartographic.fromCartesian(transformCenter);
            var boundingSphereCartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
            var height = boundingSphereCartographic.height - transformCartographic.height;
            clippingPlanes.modelMatrix = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(0.0, 0.0, height));
        }

        for (var i = 0; i < clippingPlanes.length; ++i) {
            var plane = clippingPlanes.get(i);
            var planeEntity = viewer.entities.add({
                position : boundingSphere.center,
                plane : {
                    dimensions : new Cesium.Cartesian2(radius * 2.5, radius * 2.5),
                    material : Cesium.Color.WHITE.withAlpha(0.1),
                    plane : new Cesium.CallbackProperty(createPlaneUpdateFunction(plane), false),
                    outline : true,
                    outlineColor : Cesium.Color.WHITE
                }
            });

            planeEntities.push(planeEntity);
        }
        return tileset;
    }).otherwise(function(error) {
        console.log(error);
    });
}

function loadModel(url) {
    clippingPlanes = new Cesium.ClippingPlaneCollection({
        planes : [
            new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 0.0, -1.0), 0.0)
        ],
        edgeWidth : viewModel.edgeStylingEnabled ? 1.0 : 0.0
    });

    var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 300.0);
    var heading = Cesium.Math.toRadians(135.0);
    var pitch = 0.0;
    var roll = 0.0;
    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
    var entity = viewer.entities.add({
        name : url,
        position : position,
        orientation : orientation,
        model : {
            uri : url,
            scale : 8,
            minimumPixelSize : 100.0,
            clippingPlanes : clippingPlanes
        }
    });

    viewer.trackedEntity = entity;

    for (var i = 0; i < clippingPlanes.length; ++i) {
        var plane = clippingPlanes.get(i);
        var planeEntity = viewer.entities.add({
            position : position,
            plane : {
                dimensions : new Cesium.Cartesian2(300.0, 300.0),
                material : Cesium.Color.WHITE.withAlpha(0.1),
                plane : new Cesium.CallbackProperty(createPlaneUpdateFunction(plane), false),
                outline : true,
                outlineColor : Cesium.Color.WHITE
            }
        });

        planeEntities.push(planeEntity);
    }
}

// Power Plant design model provided by Bentley Systems
var bimUrl = Cesium.IonResource.fromAssetId(8564);
var pointCloudUrl = Cesium.IonResource.fromAssetId(16421);
var instancedUrl = '../../SampleData/Cesium3DTiles/Instanced/InstancedOrientation/tileset.json';
var modelUrl = '../../SampleData/models/CesiumAir/Cesium_Air.glb';

loadTileset(bimUrl);

// Track and create the bindings for the view model
var toolbar = document.getElementById('toolbar');
Cesium.knockout.track(viewModel);
Cesium.knockout.applyBindings(viewModel, toolbar);

Cesium.knockout.getObservable(viewModel, 'currentExampleType').subscribe(function(newValue) {
    reset();

    if (newValue === clipObjects[0]) {
        loadTileset(bimUrl);
    } else if (newValue === clipObjects[1]) {
        loadTileset(pointCloudUrl);
    } else if (newValue === clipObjects[2]) {
        loadTileset(instancedUrl);
        // Position the instanced tileset above terrain
        tileset.modelMatrix = new Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(15.0, -58.6, 50.825));
    } else {
        loadModel(modelUrl);
    }
});

Cesium.knockout.getObservable(viewModel, 'debugBoundingVolumesEnabled').subscribe(function(value) {
    if (Cesium.defined(tileset)) {
        tileset.debugShowBoundingVolume = value;
    }
});

Cesium.knockout.getObservable(viewModel, 'edgeStylingEnabled').subscribe(function(value) {
    var edgeWidth = value ? 1.0 : 0.0;

    clippingPlanes.edgeWidth = edgeWidth;
});

function reset() {
    viewer.entities.removeAll();
    viewer.scene.primitives.remove(tileset);
    planeEntities = [];
    targetY = 0.0;
    tileset = undefined;
}

//Sandcastle_End
    Sandcastle.finishedLoading();
}
if (typeof Cesium !== 'undefined') {
    window.startupCalled = true;
    startup(Cesium);
}
</script>
</body>
</html>
